函数式编程之记忆
是一种时间换空间的方法,用牺牲空间的复杂度来换取时间的复杂度

字符串连接

function f() {
  var s = arguments.length + Array.prototype.join.call(arguments);
  console.log(s);
};

这里使用的是Array.prototype.join方法进行字符串连接
返回的是连接的结果

接下来,写一个具有记忆的函数

// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
  var cacho = {}; // 定义一个用于保存值的私有变量
  return function() {
    var key = arguments.length + Array.prototype.join.call(arguments, ',');
    if (key in cacho) 
      return cacho[key];
    else
      return cacho[key] = f.call(this, arguments);
  };
}

这是一个具有记忆的函数,用数组的长度和数组合并后组成的字符串作为属性名,进行保存,如果这个值存在则直接进行保存,如果值不存在则进行保存并返回(因为赋值语句会返回右值,所以return语句后无需再跟进行返回值的语句)

使用调试函数对其进行修改


// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
  var cacho = {}; // 定义一个用于保存值的私有变量
  console.log(cacho);
  return function() {
    var key = arguments.length + Array.prototype.join.call(arguments, ',');
    console.log(key);
    if (key in cacho) {
      console.log(cacho[key]);
      return cacho[key];
    }
    else {
      console.log(f.call(this,arguments));
      return cacho[key] = f.call(this, arguments);
    };
  };
}

这样就更加的明显了

使用这个函数

返回两个整数的最大公约数
欧几里得算法

由欧几里得最先发现,一个用于计算最大公因数的算法
function gcd(a, b) {
  var t;  // 用于保存中间变量
  if(a < b)  // 确保 a >= b
    t = a, a = b, b = t; 
  
  while(t != 0)
    t = a % b, a = b, b = t;
  return a;
}

利用欧几里得算法写的求两个数的最大公因数,运行一下

gcd(85, 187);
17

计算结果正确,使用刚刚实现的具有记忆功能的高阶函数,将函数传进去,生成了一个新的函数

var functiongcd = memorize(gcd);
Object {  }

使用这个函数
好吧。莫名进行死循环了。

Error: Script terminated by timeout at:
gcd@Scratchpad/1:35:9
memorize/<@Scratchpad/1:24:27
@debugger eval code:1:1

没办法继续排查错误

排查错误

// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
  var cache = {}; 
console.log(cache);
  return function() {
    var key = arguments.length + Array.prototype.join.call(arguments);
   console.log(key);
    if (key in cache) {
      console.log(cache[key]);
      return cache[key];
    }
    else {
      console.log(f.apply(this,arguments));
      return cache[key] = f.apply(this, arguments);
    };
  };
}

这个函数依旧写错了,call只能传入一个值,而apply能传入多个值

继续运行

gcdmemo(85, 187);
285,187 Scratchpad/1:17:4
17 Scratchpad/1:23:7
17

其中第一个Scratchpad/1:17:4返回指代的是

    if (key in cache) {
      console.log(cache[key]);
      return cache[key];
    }

其中第二个Scratchpad/1:23:7返回指代的是

      return cache[key] = f.apply(this, arguments);

好啦,非常明显,第一步是先将值缓存进入其私有变量,即保存进入闭包内部,然后第二个是发现这个值已经保存过了直接输出

(^o^)/,
js的记忆折腾完毕~


小小____
435 声望110 粉丝

哇哈~我在那~这是哪~每日连11问